package com.autumn.platform.web.request.impl;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.util.UrlPathHelper;

import com.autumn.platform.core.Utils;
import com.autumn.platform.core.context.reqeust.impl.Request;
import com.autumn.platform.web.request.IWebRequest;

import net.sf.uadetector.ReadableUserAgent;

public class WebRequest extends Request implements IWebRequest {

    /**
     * 
     */
    private static final long serialVersionUID = -830482074088541008L;

    private static final String[] HEADERS_TO_TRY = {
            "X-Forwarded-For",
            "Proxy-Client-IP",
            "WL-Proxy-Client-IP",
            "HTTP_X_FORWARDED_FOR",
            "HTTP_X_FORWARDED",
            "HTTP_X_CLUSTER_CLIENT_IP",
            "HTTP_CLIENT_IP",
            "HTTP_FORWARDED_FOR",
            "HTTP_FORWARDED",
            "HTTP_VIA",
            "REMOTE_ADDR",
            "X-Real-IP"
    };

    private static final UrlPathHelper urlPathHelper = new UrlPathHelper();

    /**
     * 获取Spring MVC封装的请求对象
     */
    private final NativeWebRequest nativeWebRequest;

    /**
     * HTTP方法
     */
    private final String httpMethod;

    /**
     * 请求Url
     */
    private final String requestUrl;

    /**
     * 客户端IP
     */
    private final String clientIp;

    /**
     * 客户端操作系统
     */
    private final String clientOs;

    /**
     * 用户代理
     */
    private final String userAgent;

    /**
     * 客户端设备
     */
    private final String clientDevice;

    /**
     * 客户端浏览器
     */
    private final String clientBrowser;

    @SuppressWarnings("deprecation")
    public WebRequest(HttpServletRequest request, HttpServletResponse response) {
        super(request.getSession(true).getId());
        this.nativeWebRequest = new ServletWebRequest(request, response);
        this.httpMethod = request.getMethod();
        this.requestUrl = urlPathHelper.getLookupPathForRequest(request);
        super.setTarget(this.requestUrl);
        super.setProtocol(request.getProtocol());

        this.userAgent = request.getHeader("User-Agent");
        this.clientIp = getClientIpAddress(request);

        ReadableUserAgent agent = UserAgentUtils.parseUserAgent(userAgent);
        this.clientOs = agent.getOperatingSystem().getName() + agent.getOperatingSystem().getVersionNumber().toVersionString();
        this.clientDevice = agent.getTypeName();

        UserAgent agent1 = UserAgent.parseUserAgent(userAgent);
        this.clientBrowser = agent1.getBrowser();
    }

    @Override
    public NativeWebRequest getNativeWebRequest() {
        return this.nativeWebRequest;
    }

    @Override
    public String getHttpMethod() {
        return this.httpMethod;
    }

    @Override
    public String getRequestUrl() {
        return this.requestUrl;
    }

    @Override
    public String getClientIp() {
        return this.clientIp;
    }

    @Override
    public String getClientOs() {
        return this.clientOs;
    }

    @Override
    public String getUserAgent() {
        return this.userAgent;
    }

    @Override
    public String getClientBrowser() {
        return this.clientBrowser;
    }

    @Override
    public String getClientDevice() {
        return this.clientDevice;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("WebRequest:{");
        sb.append("requestId:\"" + this.getRequestId());
        sb.append("\",server:\"" + this.getServerIp());
        sb.append("\",httpMethod:\"" + this.getHttpMethod());
        sb.append("\",requestUrl:\"" + this.getRequestUrl());
        sb.append("\"}");
        return sb.toString();
    }

    public static String getClientIpAddress(HttpServletRequest request) {
        String ip = getRemoteIpAddress(request);
        return Utils.convertIp(ip);
    }

    private static String getRemoteIpAddress(HttpServletRequest request) {
        for (String header : HEADERS_TO_TRY) {
            String ip = request.getHeader(header);
            if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
                return ip;
            }
        }
        return request.getRemoteAddr();
    }
}
